<template>
  <div class="f-table-wrapper" ref="wrapper">
    <div :style="{height,overflow:'auto'}" ref="tableWrapper">
      <!--  -->
      <table class="f-table" :class="{ bordered, compact, striped }" ref="table">
        <thead>
        <tr>
          <th v-if="expendField" :style="{width:'50px'}" class="f-table-center"></th>
          <th v-if="checkable" :style="{width:'50px'}" class="f-table-center">
            <input type="checkbox" @change="onChangeAllItems" ref="allChecked" :checked="areAllItemsSelected"/>
          </th>
          <th v-for="column in columns" :key="column.field" :style="{width:column.width+'px'}">
            <div class="f-table-header">
              {{ column.text }}
              <span v-if="column.field in orderBy" class="f-table-sorter" @click="changeOrderBy(column.field)">
                <f-icon name="asc" :class="{active:orderBy[column.field]==='asc'}"></f-icon>
                <f-icon name="desc" :class="{active:orderBy[column.field]==='desc'}"></f-icon>
              </span>
            </div>
          </th>
          <th v-if="$scopedSlots.default" ref="actionsHeader"></th>
        </tr>
        </thead>
        <!--  -->
        <tbody>
          <template v-for="(item,index) in dataSource">
            <tr :key="item.id">
              <td v-if="expendField" :style="{width:'50px'}" class="f-table-center"><f-icon name="right" class="f-table-expendIcon" @click="expendItem(item.id)"></f-icon></td>
              <td v-if="checkable" :style="{width:'50px'}" class="f-table-center">
                <input type="checkbox" @change="onChangeItem(item, index, $event)" :checked="inSelectedItems(item)"/>
              </td>
              <template v-for="column in columns">
                <td :key="column.field" :style="{width:column.width+'px'}">
                  <template v-if="column.render">
                    <vnodes :vnodes="column.render({value:item[column.field]})"></vnodes>
                  </template>
                  <template v-else>
                    {{item[column.field]}}
                  </template>
                </td>
              </template>
              <td v-if="$scopedSlots.default">
                <div ref="actions" style="display:inline-block;">
                  <slot :item="item" frank="18"></slot>
                </div>
              </td>
            </tr>
            <!--↓需要被展开的-->
            <tr v-if="inExpendedIds(item.id)" :key="`${item.id}-expend`">
              <td :colspan="columns.length + expendedCellColSpan">
                {{item[expendField]||'空'}}
              </td>
            </tr>
          </template>

        </tbody>
      </table>
    </div>
    <div class="f-table-loading" v-if="loading">
        <f-icon name="loading"></f-icon>
    </div>
  </div>
</template>

<script>
import FIcon from "./components/icon";

export default {
  name: "FTable",
  components: {
    FIcon
    ,vnodes:{
      functional:true
      , render: (h, context) => context.props.vnodes
    }
  },
  props: {
    height:{
      // type:[Number,String]
      type:Number
    },
    expendField:{
      type:String
    },
    orderBy: {
      type: Object,
      default: () => ({})
    },
    loading:{
      type:Boolean
      ,default:false
    },
    /*columns: {
      type: Array,
      required: true
    },*/
    dataSource: {
      type: Array,
      required: true,
      validator(array) {
        return array.filter(item => item.id === undefined).length <= 0;
      }
    },
    bordered: {
      type: Boolean,
      default: false
    },
    compact: {
      type: Boolean,
      default: false
    },
    striped: {
      type: Boolean,
      default: true
    },
    selectedItems: {
      type: Array,
      default: () => []
    },
    checkable:{
      type:Boolean
      ,default:false
    }
  },
  data(){
    return {
      expendedIds:[]
      ,columns:[]
    }
  },
  mounted(){
    this.columns = this.$slots.default.map(node => {
      let {text, field, width} = node.componentOptions.propsData;
      let render = node.data.scopedSlots && node.data.scopedSlots.default;
      return {text, field, width, render};
    });

    let table2 = this.$refs.table.cloneNode(false); //true 后代也会被复制
    this.table2 = table2;
    table2.classList.add('f-table-copy');
    let tHead = this.$refs.table.children[0];
    let {height} = tHead.getBoundingClientRect();
    this.$refs.tableWrapper.style.marginTop = height + 'px';
    this.$refs.tableWrapper.style.height = this.height - height + 'px';
    table2.appendChild(tHead);
    this.$refs.wrapper.appendChild(table2);
    /*this.updateHeadersWidth();
    this.onWindowResize = () => {
      this.updateHeadersWidth();
    };
    window.addEventListener('resize', this.onWindowResize);*/

    if(this.$scopedSlots.default){
      let div = this.$refs.actions[0];
      let {width} = div.getBoundingClientRect();
      let parent = div.parentNode;
      let styles = getComputedStyle(parent);
      let paddingLeft = styles.getPropertyValue('padding-left');
      let paddingRight = styles.getPropertyValue('padding-right');
      let borderLeft = styles.getPropertyValue('border-left-width');
      let borderRight = styles.getPropertyValue('border-right-width');
      let w = width + parseInt(paddingRight) + parseInt(paddingLeft) + parseInt(borderLeft) + parseInt(borderRight) + 'px';
      console.log(w);
      this.$refs.actionsHeader.style.width = w;
      this.$refs.actions.map(div=>{
        div.parentNode.style.width = w;
      })
    }
  },
  beforeDestroy(){
    this.table2.remove();
    // window.removeEventListener('resize', this.onWindowResize);
  },
  computed: {
    areAllItemsSelected() {
      const a = this.dataSource.map(item => item.id).sort(); //默认字典排序，默认即可
      const b = this.selectedItems.map(item => item.id).sort();
      let equal = false;
      if (a.length !== b.length) {
        return false;
      }
      for (let i = 0; i < a.length; ++i) {
        if (a[i] !== b[i]) {
          equal = false;
          break;
        }
      }
      return equal;
    }
    ,expendedCellColSpan(){
      let result = 0;
      if(this.checkable) result += 1;
      if(this.expendField) result += 1;
      return result;
    }
  },
  watch: {
    selectedItems() {
      if (this.selectedItems.length === this.dataSource.length) {
        this.$refs.allChecked.indeterminate = false;
      } else if (this.selectedItems.length === 0) {
        this.$refs.allChecked.indeterminate = false;
      } else {
        this.$refs.allChecked.indeterminate = true;
      }
    }
  },
  methods: {
    expendItem(id){
      if(this.inExpendedIds(id)){
        this.expendedIds.splice(this.expendedIds.indexOf(id), 1);
      }else{
        this.expendedIds.push(id);
      }
    },
    inExpendedIds(id){
      return this.expendedIds.indexOf(id) >= 0;
    },
    // updateHeadersWidth(){
    //   let table2 = this.table2;
    //   let tableHeader = Array.from(this.$refs.table.children).filter(node=>node.tagName.toLowerCase()==='thead')[0];
    //   let tableHeader2;
    //   Array.from(table2.children).map(node => {
    //     if (node.tagName.toLowerCase() !== 'thead') {
    //       node.remove();
    //     }else{
    //       tableHeader2 = node;
    //     }
    //   });
    //   Array.from(tableHeader.children[0].children).map((th,i) => {
    //     console.log(th.getBoundingClientRect());
    //     const {width} = th.getBoundingClientRect();
    //     tableHeader2.children[0].children[i].style.width = width + 'px'; //TODO 还是有问题 borderbox貌似无效
    //   });
    // },
    changeOrderBy(key,value){
      //这么做是为了 手机端操作
      const copy = JSON.parse(JSON.stringify(this.orderBy));
      let oldValue = copy[key];
      if(oldValue === 'asc'){
        copy[key] = 'desc';
      }else if(oldValue === 'desc'){
        copy[key] = true;
      }else{
        copy[key] = 'asc';
      }
      this.$emit('update:orderBy', copy);
    },
    inSelectedItems(item) {
      return this.selectedItems.filter(i => i.id === item.id).length > 0;
    },
    onChangeItem(item, index, e) {
      // console.log(e.target.checked);
      let selected = e.target.checked;
      let copy = JSON.parse(JSON.stringify(this.selectedItems));
      if (selected) {
        copy.push(item);
      } else {
        // copy.splice(copy.map(item=>item.id).indexOf(item.id), 1);
        copy = copy.filter(i => i.id !== item.id);
      }
      this.$emit("update:selectedItems", copy);
    },
    onChangeAllItems(e) {
      let selected = e.target.checked;
      if (selected) {
        this.$emit("update:selectedItems", this.dataSource);
      } else {
        this.$emit("update:selectedItems", []);
      }
    }
  }
};
</script>

<style lang="scss">
@import "./components/var";
$grey: darken($grey, 10%);
.f-table {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
  //border:1px solid $grey;
  border-bottom: 1px solid $grey;
  &.bordered {
    border: 1px solid $grey;
    td,
    th {
      border: 1px solid $grey;
    }
  }
  &.compact {
    td,
    th {
      padding: 4px;
    }
  }
  td,
  th {
    //border:1px solid $grey;
    border-bottom: 1px solid $grey;
    text-align: left;
    padding: 8px;
  }
  &.striped {
    tbody {
      > tr {
        &:nth-child(odd) {
          background: white;
        }
        &:nth-child(even) {
          background: lighten($grey, 13%);
        }
      }
    }
  }

  &-sorter {
    display: inline-flex;
    flex-direction: column;
    margin: 0 4px;
    svg {
      width: 9px;
      height: 9px;
      fill: $grey;
      cursor: pointer;
        &.active{fill:red;}
      &:first-child {
        position: relative;
        bottom: -1px;
      }
      &:first-child(2) {
        position: relative;
        top: -1px;
      }
    }
  }

  &-header {
    display: flex;
    align-items: center;
  }

    &-wrapper{
      position:relative;
      overflow:auto;
    }
    &-loading{
        position:absolute;
        top:0;
        left:0;
        width: 100%;
        height: 100%;
        display:flex;
        justify-content: center;
        align-items: center;
        background: rgba(255,255,255,.7);
        svg{
            width: 50px;
            height: 50px;
            @include spin;
        }
    }
  &-copy{
    position:absolute;
    left:0;
    top:0;
    width: 100%;
    background: #fff;
  }
  &-expendIcon{
    width:10px;
    height:10px;
  }
  & &-center{
    text-align: center;
  }
}
</style>
